package com.example.config;

import com.example.config.handler.MyAuthenticationFailureHandler;
import com.example.config.handler.MyAuthenticationSuccessHandler;
import com.example.config.handler.MyLogoutSuccessHandler;
import com.example.constant.Constants;
import com.example.filter.TokenVerifyFilter;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class SecurityConfig {
    @Resource
    private TokenVerifyFilter tokenVerifyFilter;
    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

//    You have entered a password with no PasswordEncoder
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,
                                                   CorsConfigurationSource corsConfigurationSource) throws Exception {
        return httpSecurity
                .formLogin((formLogin) ->{
                    formLogin.loginProcessingUrl(Constants.LOGIN_URI)
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })
//                放过登录请求方法，其余方法均需要先登录后，才能通过
                .authorizeHttpRequests(authorize -> {
                    authorize.requestMatchers("/api/login").permitAll()
                            .anyRequest().authenticated();
                })
                //                禁用跨站伪造请求
                .csrf(csrf -> {
                    csrf.disable();
                })
//                允许跨域请求
                .cors(cors -> {
                    cors.configurationSource(corsConfigurationSource);
                })
//                无session状态，也就是禁用session
                .sessionManagement((session)->{
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
//                添加自定义的filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)
//                退出提交到/api/loginout地址，不需要我们在controller中些，是框架处理
                .logout((logout) -> {
                    logout.logoutUrl("/api/loginOut")
                            .logoutSuccessHandler(myLogoutSuccessHandler);
                })
                .build();
    }
}
